package com.yutao.service.matchService;

import com.yutao.domain.MatchMessage;
import com.yutao.domain.Player;
import com.yutao.domain.PoolPlayer;
import com.yutao.mapper.MatchPool;
import com.yutao.utils.JsonUtils;
import com.yutao.utils.RedisListenerBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;

import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;

@Component
public class MatchPoolImpl implements MatchPool {

    @Autowired
    public RedisTemplate redisTemplate;

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    @Autowired
    private RedisListenerBean redisListener;


    private ExecutorService pools;

    private List<PoolPlayer> pool;
    private int increaseTime;

    MatchPoolImpl() {
        pool = new CopyOnWriteArrayList<>();
    }

    public int getPoolSize(){
        return pool.size();
    }

    public void addPlayer(PoolPlayer poolPlayer) {
        pool.add(poolPlayer);
    }

    public boolean checkMatch(PoolPlayer a, PoolPlayer b) {
        int scoreGap = Math.abs(a.getScore() - b.getScore());
        int aMaxDiff = a.getWaitingTime() * increaseTime;
        int bMaxDiff = b.getWaitingTime() * increaseTime;
        return scoreGap <= aMaxDiff && scoreGap <= bMaxDiff;
    }


    @Override
    public void match(int number) {
        //这里把匹配人数写活
        while (pool.size() >= number) {
            pool.sort(Comparator.comparingInt(PoolPlayer::getScore));
            /*
              这里利用了滑动窗口的思想，
              如果还用之前的list存在匹配的人，当每有
             */
            List<PoolPlayer> list = new CopyOnWriteArrayList<>();
            boolean flag = true;
            for (int t = 0; t < pool.size() - number + 1; t++) {
                //匹配第一组人
                if (t == 0) {
                    //从池中拿出number个人
                    for (int i = 0; i < number; i++) {
                        list.add(pool.get(t + i));
                    }
                    for (int i = 0; i < list.size(); i++) {
                        for (int j = 0; j < list.size(); j++) {
                            if (i == j) continue;
                            if (!checkMatch(list.get(i), list.get(j))) {
                                flag = false;
                                break;
                            }
                        }
                        if (!flag) {
                            break;
                        }
                    }
                } else {
                    //当指针移动时
                    list.remove(0);
                    PoolPlayer newPoolPlayer = pool.get(t + number - 1);
                    list.add(newPoolPlayer);
                    for (int i = 0; i < number; i++) {
                        if (!checkMatch(list.get(i), newPoolPlayer)) {
                            flag = false;
                            break;
                        }
                    }
                }
                if (flag) {
                    matchSuccess(list);
                    pool.removeAll(list);
                    break;
                }
            }
            if (flag) {
                break;
            }

        }
    }

    @Override
    public void matchSuccess(List<PoolPlayer> list) {
        String roomName = list.get(0).getUuid();
        redisListener.setRoom(roomName);
        List<Player>players = new CopyOnWriteArrayList<>();
        for (PoolPlayer x : list) {
            players.add(new Player(x.getUuid(),x.getUsername(),x.getPhoto()));
        }
        redisListener.listenerAdapter(players);
        for (PoolPlayer x : list) {
            //向频道内的玩家发送消息
            MatchMessage matchMessage = new MatchMessage("group_send_event","create_player",x.getUsername(),x.getPhoto(),x.getUuid());
            simpMessagingTemplate.convertAndSend(roomName, JsonUtils.parseObjToJson(matchMessage));
        }

    }

    @Override
    public void increase_waiting_time() {
        pool.forEach(PoolPlayer::increaseWaitingTime);
    }


}
